// MIDI轨道播放器 - 核心逻辑
document.addEventListener('DOMContentLoaded', () => {
    // DOM元素
    const fileInput = document.getElementById('midiFile');
    const selectFileBtn = document.getElementById('selectFileBtn');
    const trackSelect = document.getElementById('trackSelect');
    const connectBtn = document.getElementById('connectBtn');
    const playBtn = document.getElementById('playBtn');
    const stopBtn = document.getElementById('stopBtn');
    const statusText = document.getElementById('statusText');
    const trackInfo = document.getElementById('trackInfo');
    const serialLog = document.getElementById('serialLog');

    // 状态变量
    let midiData = null;
    let selectedTrack = null;
    let port = null;
    let isPlaying = false;
    let startTime = 0;
    let scheduledEvents = [];
    let currentEventIndex = 0;
    let selectedBaudRate = 115200; // 默认波特率

    // 选择文件按钮点击事件
    selectFileBtn.addEventListener('click', () => {
        fileInput.click();
    });

    // 文件选择处理 - 增强版
    fileInput.addEventListener('change', async (e) => {
        const file = e.target.files[0];
        if (!file) {
            console.log('未选择文件');
            return;
        }

        try {
            statusText.textContent = '解析MIDI文件中...';
            console.log('开始解析文件:', file.name);

            const arrayBuffer = await file.arrayBuffer();
            console.log('文件读取完成，开始解析MIDI数据');
            console.log('原始文件大小:', arrayBuffer.byteLength, 'bytes');

            try {
                // 临时保存原始数据用于调试
                const rawData = new Uint8Array(arrayBuffer);
                console.log('原始MIDI文件头:', Array.from(rawData.slice(0, 4)).map(b => b.toString(16)).join(' '));

                // 解析MIDI文件
                midiData = parseMidiFile(arrayBuffer);

                // 兼容不同的解析器输出格式
                if (!midiData.header) {
                    console.warn('解析器返回的数据缺少header信息，尝试手动提取');
                    midiData.header = {
                        formatType: rawData[9] << 8 | rawData[10],
                        tracksCount: rawData[11] << 8 | rawData[12],
                        ticksPerQuarter: rawData[13] << 8 | rawData[14]
                    };
                }

                console.log('MIDI解析完成，文件类型:', midiData.header.formatType);
                console.log('轨道数:', midiData.header.tracksCount);

                // 详细检查每个轨道
                if (!midiData.tracks) {
                    console.warn('解析器返回的数据缺少tracks数组，尝试手动处理');
                    midiData.tracks = [];

                    // 简单示例：创建一个空轨道
                    midiData.tracks.push({
                        events: [],
                        name: '轨道 0'
                    });
                }

                midiData.tracks.forEach((track, i) => {
                    console.group(`轨道 ${i} 检查`);

                    // 确保有events数组
                    if (!track.events) {
                        console.warn('轨道缺少events属性，初始化为空数组');
                        track.events = [];
                    }

                    console.log('轨道名称:', track.name || '未命名');
                    console.log('轨道事件数:', track.events.length);

                    if (track.events.length > 0) {
                        console.log('第一个事件:', track.events[0]);
                        console.log('最后一个事件:', track.events[track.events.length - 1]);
                    } else {
                        console.warn('此轨道没有事件数据');
                    }
                    console.groupEnd();
                });

                // 检查是否有音符事件或只有元事件
                const hasNoteEvents = midiData.tracks.some(track =>
                    track.events.some(e => e.type === 'noteOn' || e.type === 'noteOff')
                );

                if (!hasNoteEvents) {
                    const hasMetaEvents = midiData.tracks.some(track =>
                        track.events.some(e => e.type && e.type.startsWith('meta'))
                    );

                    if (hasMetaEvents) {
                        console.warn('提示: 此MIDI文件只包含控制信息(如拍号、速度)，没有音符事件');
                        console.log('包含的元事件类型:',
                            [...new Set(midiData.tracks.flatMap(t =>
                                t.events.filter(e => e.type && e.type.startsWith('meta'))
                                    .map(e => e.type)
                            ))]);
                    } else {
                        console.error('警告: 解析后的MIDI数据不包含任何事件');
                    }

                    // 创建十六进制转储
                    const hexDump = Array.from(rawData).map(b =>
                        b.toString(16).padStart(2, '0')
                    ).join(' ');

                    console.log('文件前256字节的十六进制转储:');
                    console.log(hexDump.slice(0, 512));

                    // 提供下载原始数据的选项和详细分析
                    const blob = new Blob([arrayBuffer], { type: 'application/octet-stream' });
                    const url = URL.createObjectURL(blob);
                    console.log('下载原始MIDI文件分析:', url);

                    // 分析轨道数据块
                    const trackChunkOffset = 14; // 跳过文件头
                    const trackChunkHeader = Array.from(rawData.slice(trackChunkOffset, trackChunkOffset + 8));
                    console.log('轨道块头部:', trackChunkHeader.map(b => b.toString(16)).join(' '));

                    // 检查是否为"MTrk"
                    if (trackChunkHeader[0] === 0x4D && trackChunkHeader[1] === 0x54 &&
                        trackChunkHeader[2] === 0x72 && trackChunkHeader[3] === 0x6B) {
                        const trackLength = (trackChunkHeader[4] << 24) |
                            (trackChunkHeader[5] << 16) |
                            (trackChunkHeader[6] << 8) |
                            trackChunkHeader[7];
                        console.log('轨道块长度:', trackLength, 'bytes');

                        // 显示轨道块前32字节内容
                        const trackDataStart = trackChunkOffset + 8;
                        const trackDataPreview = Array.from(rawData.slice(trackDataStart, trackDataStart + 32))
                            .map(b => b.toString(16).padStart(2, '0')).join(' ');
                        console.log('轨道数据预览:', trackDataPreview);
                    } else {
                        console.error('错误: 无效的轨道块标记');
                    }
                }
            } catch (e) {
                console.error('MIDI解析失败:', e);
                console.log('错误发生时的部分数据:', new Uint8Array(arrayBuffer).slice(0, 32));
                throw new Error(`无法解析MIDI文件: ${e.message}`);
            }

            // 清空并填充轨道选择下拉框
            trackSelect.innerHTML = '<option value="">-- 选择轨道 --</option>';
            midiData.tracks.forEach((track, index) => {
                const option = document.createElement('option');
                option.value = index;
                const eventCount = track.events ? track.events.length : 0;
                option.textContent = track.name || `轨道 ${index + 1} (${eventCount}事件)`;
                trackSelect.appendChild(option);
                console.log(`添加轨道选项 ${index}:`, track);
            });

            // 确保选择框可用并默认选中第一个轨道
            trackSelect.disabled = false;
            if (midiData.tracks.length > 0) {
                trackSelect.value = "0";
                selectedTrack = midiData.tracks[0];
                updateTrackInfo();
            }

            statusText.textContent = `已加载: ${file.name} (${midiData.tracks.length}个轨道)`;
            console.log('轨道选择下拉框已更新', {
                options: trackSelect.options.length,
                selectedIndex: trackSelect.selectedIndex,
                disabled: trackSelect.disabled
            });

            updateTrackInfo();

            // 完整性检查
            console.log('=== 文件加载完整性检查 ===');
            console.log('文件名称:', file.name);
            console.log('轨道数量:', midiData.tracks.length);
            midiData.tracks.forEach((track, i) => {
                console.log(`轨道 ${i} 事件数:`, track.events.length);
            });
            console.log('当前选择的轨道:', trackSelect.value);
            console.log('=======================');

        } catch (error) {
            console.error('文件处理错误:', error);
            statusText.textContent = `错误: 无法解析文件 ${file.name}`;
            trackSelect.innerHTML = '<option value="">-- 解析失败 --</option>';
            trackSelect.disabled = true;

            // 错误时清除数据
            midiData = null;
            selectedTrack = null;
        }
    });

    // 轨道选择变化事件
    trackSelect.addEventListener('change', () => {
        console.log('--- 轨道选择变化事件触发 ---');
        console.log('当前选择的值:', trackSelect.value);

        const trackIndex = parseInt(trackSelect.value);
        if (!isNaN(trackIndex) && midiData) {
            selectedTrack = midiData.tracks[trackIndex];
            updateTrackInfo();
            playBtn.disabled = port ? false : true;
        } else {
            selectedTrack = null;
            playBtn.disabled = true;
        }
    });

    // 波特率选择事件
    const baudRateSelect = document.getElementById('baudRateSelect');
    baudRateSelect.addEventListener('change', (e) => {
        selectedBaudRate = parseInt(e.target.value);
        console.log('波特率更改为:', selectedBaudRate);
    });

    // 连接串口按钮点击事件
    connectBtn.addEventListener('click', async () => {
        try {
            if (!port) {
                // 请求串口连接
                port = await navigator.serial.requestPort();
                await port.open({ baudRate: selectedBaudRate });

                // 创建接收数据UI元素
                const receiveContainer = document.createElement('div');
                receiveContainer.id = 'receive-container';
                receiveContainer.innerHTML = `
                    <h3>串口接收数据</h3>
                    <div id="received-data" class="serial-data"></div>
                `;


                // 设置数据接收处理
                currentReader = port.readable.getReader();

                async function readSerialData() {
                    try {
                        while (port.readable ) {
                            console.log(currentReader)
                            const { value, done } = await currentReader.read();
                            if (done) break;

                            // 解码接收到的数据
                            const textDecoder = new TextDecoder();
                            const decodedData = textDecoder.decode(value);


                            // 记录到日志
                            logSerialMessage(`接收: ${decodedData.trim()}`);
                        }
                    } catch (error) {
                        logSerialMessage(`数据接收错误: ${error.message}`);
                        console.error(error);
                    }finally {
                        if (port.readable) {
                            currentReader.releaseLock();
                        }
                        logSerialMessage('释放串口锁');
                    }
                }

                readSerialData();

                connectBtn.textContent = '断开连接';
                statusText.textContent = '串口已连接';
                logSerialMessage('串口连接成功');

                if (selectedTrack) {
                    playBtn.disabled = false;
                }
            } else {
                try {
                    if (currentWriter) {
                        currentWriter.releaseLock();
                        currentWriter = null;
                    }
                    if (currentReader) {
                        console.log(currentReader)
                       await currentReader.cancel(); // 终止当前读取操作
                       await currentReader.releaseLock();
                        currentReader = null;
                    };
                } catch (e) {
                    logSerialMessage(`释放串口锁失败: ${e.message}`);
                }

                
                stopPlayback();
                console.log(port);

                // 断开串口连接
                await port.close();
                port = null;

                // 移除接收数据显示区域
                const receiveContainer = document.getElementById('receive-container');
                if (receiveContainer) {
                    receiveContainer.remove();
                }

                connectBtn.textContent = '连接串口';
                statusText.textContent = '串口已断开';
                logSerialMessage('串口已断开');
                playBtn.disabled = true;
            }
        } catch (error) {
            statusText.textContent = `串口错误: ${error.message}`;
            logSerialMessage(`错误: ${error.message}`);
            console.error(error);
        }
    });

    // 播放按钮点击事件
    playBtn.addEventListener('click', () => {
        if (!isPlaying && selectedTrack && port) {
            startPlayback();
        }
    });

    // 停止按钮点击事件
    stopBtn.addEventListener('click', () => {
        stopPlayback();
    });

    // 解析MIDI文件
    function parseMidiFile(arrayBuffer) {
        const dataView = new DataView(arrayBuffer);
        let offset = 0;

        // 检查文件头
        const headerChunk = readChunk(dataView, offset);
        offset += 8; // 跳过头部

        if (headerChunk.id !== 'MThd') {
            throw new Error('无效的MIDI文件: 缺少MThd头部');
        }

        // 解析头部信息
        const format = dataView.getUint16(offset);
        const tracksCount = dataView.getUint16(offset + 2);
        const timeDivision = dataView.getUint16(offset + 4);
        offset += 6;

        console.log('MIDI文件头:', {
            format,
            tracksCount,
            timeDivision
        });

        const tracks = [];

        // 解析每个轨道块
        for (let i = 0; i < tracksCount; i++) {
            const trackChunk = readChunk(dataView, offset);
            offset += 8;

            if (trackChunk.id !== 'MTrk') {
                console.warn(`轨道 ${i} 有无效的块ID: ${trackChunk.id}`);
                continue;
            }

            const track = {
                name: `轨道 ${i + 1}`,
                events: []
            };

            let trackEnd = offset + trackChunk.length;
            let runningStatus = null;
            let absoluteTime = 0;

            // 解析轨道事件
            while (offset < trackEnd) {
                const deltaTime = readVariableLength(dataView, offset);
                offset += deltaTime.length;
                absoluteTime += deltaTime.value;

                let eventType = dataView.getUint8(offset);
                offset++;

                // 处理运行状态
                if (eventType < 0x80) {
                    if (!runningStatus) {
                        throw new Error('无效的运行状态');
                    }
                    offset--; // 回退
                    eventType = runningStatus;
                } else {
                    runningStatus = (eventType !== 0xFF && eventType !== 0xF0 && eventType !== 0xF7) ? eventType : null;
                }

                const event = {
                    deltaTime: deltaTime.value,
                    absoluteTime,
                    type: getEventType(eventType),
                    channel: (eventType & 0x0F) + 1
                };

                // 解析事件数据
                if (eventType >= 0x80 && eventType <= 0xEF) {
                    // MIDI通道事件
                    switch (eventType & 0xF0) {
                        case 0x80: // Note Off
                        case 0x90: // Note On
                            event.noteNumber = dataView.getUint8(offset++);
                            event.velocity = dataView.getUint8(offset++);
                            if ((eventType & 0xF0) === 0x90 && event.velocity === 0) {
                                event.type = 'noteOff';
                            }
                            break;
                        case 0xA0: // Aftertouch
                            event.noteNumber = dataView.getUint8(offset++);
                            event.amount = dataView.getUint8(offset++);
                            break;
                        case 0xB0: // Controller
                            event.controllerType = dataView.getUint8(offset++);
                            event.value = dataView.getUint8(offset++);
                            break;
                        case 0xC0: // Program Change
                            event.programNumber = dataView.getUint8(offset++);
                            break;
                        case 0xD0: // Channel Aftertouch
                            event.amount = dataView.getUint8(offset++);
                            break;
                        case 0xE0: // Pitch Bend
                            event.value = (dataView.getUint8(offset++) << 7) | dataView.getUint8(offset++);
                            break;
                    }
                } else if (eventType === 0xFF) {
                    // 元事件
                    const metaType = dataView.getUint8(offset++);
                    const length = readVariableLength(dataView, offset);
                    offset += length.length;

                    event.metaType = metaType;
                    event.data = [];

                    for (let j = 0; j < length.value; j++) {
                        event.data.push(dataView.getUint8(offset++));
                    }

                    // 处理特定元事件
                    switch (metaType) {
                        case 0x03: // 轨道名称
                            track.name = String.fromCharCode.apply(null, event.data);
                            break;
                        case 0x51: // 速度
                            event.tempo = (event.data[0] << 16) | (event.data[1] << 8) | event.data[2];
                            break;
                        case 0x58: // 拍号
                            event.timeSignature = {
                                numerator: event.data[0],
                                denominator: Math.pow(2, event.data[1]),
                                clocksPerMetronome: event.data[2],
                                thirtySecondsPerQuarter: event.data[3]
                            };
                            break;
                        case 0x59: // 调号
                            event.keySignature = {
                                key: event.data[0],
                                scale: event.data[1]
                            };
                            break;
                    }
                } else if (eventType === 0xF0 || eventType === 0xF7) {
                    // 系统独占事件
                    const length = readVariableLength(dataView, offset);
                    offset += length.length;

                    event.data = [];
                    for (let j = 0; j < length.value; j++) {
                        event.data.push(dataView.getUint8(offset++));
                    }
                }

                track.events.push(event);
            }

            tracks.push(track);
        }

        return {
            format,
            timeDivision,
            tracks
        };

        // 读取块信息
        function readChunk(dataView, offset) {
            return {
                id: String.fromCharCode(
                    dataView.getUint8(offset),
                    dataView.getUint8(offset + 1),
                    dataView.getUint8(offset + 2),
                    dataView.getUint8(offset + 3)
                ),
                length: dataView.getUint32(offset + 4)
            };
        }

        // 读取可变长度值
        function readVariableLength(dataView, offset) {
            let value = 0;
            let length = 0;
            let byte;

            do {
                byte = dataView.getUint8(offset + length);
                value = (value << 7) | (byte & 0x7F);
                length++;
            } while (byte & 0x80);

            return { value, length };
        }

        // 获取事件类型名称
        function getEventType(eventType) {
            switch (eventType & 0xF0) {
                case 0x80: return 'noteOff';
                case 0x90: return 'noteOn';
                case 0xA0: return 'aftertouch';
                case 0xB0: return 'controller';
                case 0xC0: return 'programChange';
                case 0xD0: return 'channelAftertouch';
                case 0xE0: return 'pitchBend';
                case 0xF0:
                    if (eventType === 0xFF) return 'meta';
                    if (eventType === 0xF0 || eventType === 0xF7) return 'sysex';
                    return 'system';
                default: return 'unknown';
            }
        }
    }

    // 更新轨道信息显示
    function updateTrackInfo() {
        console.group('updateTrackInfo');
        console.log('函数调用时间:', new Date().toLocaleTimeString());

        try {
            if (selectedTrack) {
                const eventCount = selectedTrack.events.length;
                const duration = calculateTrackDuration(selectedTrack);
                const noteEvents = selectedTrack.events.filter(e => e.type === 'noteOn').length;

                // 格式化时间显示
                const minutes = Math.floor(duration / 60);
                const seconds = Math.floor(duration % 60);
                const milliseconds = Math.floor((duration % 1) * 1000);
                const durationStr = `${minutes}:${seconds.toString().padStart(2, '0')}.${milliseconds.toString().padStart(3, '0')}`;

                console.log('轨道详情:', {
                    eventCount,
                    duration,
                    durationStr,
                    noteEvents,
                    firstEvent: selectedTrack.events[0],
                    lastEvent: selectedTrack.events[eventCount - 1]
                });

                trackInfo.innerHTML = `
                    <p>轨道名称: ${selectedTrack.name || '未命名'}</p>
                    <p>事件总数: ${eventCount}</p>
                    <p>音符事件: ${noteEvents}</p>
                    <p>持续时间: ${durationStr}</p>
                `;
            } else {
                console.log('无选中轨道');
                trackInfo.innerHTML = '<h3>轨道信息</h3><p>未选择轨道</p>';
            }
        } catch (error) {
            console.error('更新轨道信息出错:', error);
            trackInfo.innerHTML = '<h3>轨道信息</h3><p>轨道信息更新失败</p>';
        } finally {
            console.groupEnd();
        }
    }

    // 计算轨道持续时间
    function calculateTrackDuration(track) {
        if (!track || !track.events || track.events.length === 0) return 0;

        let totalTime = 0;
        let totalTicks = 0;
        let microsecondsPerBeat = 500000; // 默认120bpm
        let ticksPerBeat = midiData ? midiData.timeDivision : 480; // 默认480 ticks/beat
        let tempoChanges = 0;

        // 查找初始速度设置
        for (const event of track.events) {
            if (event.type === 'meta' && event.metaType === 0x51) {
                microsecondsPerBeat = event.tempo;
                break;
            }
        }

        track.events.forEach(event => {
            totalTicks += event.deltaTime;

            // 处理速度变化事件
            if (event.type === 'meta' && event.metaType === 0x51) {
                microsecondsPerBeat = event.tempo;
                tempoChanges++;
            }

            // 计算事件时间(秒)
            const beats = event.deltaTime / ticksPerBeat;
            const seconds = beats * (microsecondsPerBeat / 1000000);
            totalTime += seconds;
        });

        // 计算基于最终速度的总时间(用于验证)
        const referenceTime = (totalTicks / ticksPerBeat) * (microsecondsPerBeat / 1000000);

        console.log('轨道持续时间计算:', {
            totalTicks,
            ticksPerBeat,
            tempoChanges,
            finalTempo: Math.round(60000000 / microsecondsPerBeat),
            calculatedTime: totalTime,
            referenceTime,
            difference: Math.abs(totalTime - referenceTime),
            formattedDuration: formatDuration(totalTime)
        });

        return totalTime;
    }

    // 格式化时间为MM:SS.mmm
    function formatDuration(seconds) {
        const mins = Math.floor(seconds / 60);
        const secs = Math.floor(seconds % 60);
        const ms = Math.round((seconds % 1) * 1000);
        return `${mins}:${secs.toString().padStart(2, '0')}.${ms.toString().padStart(3, '0')}`;
    }

    // 开始播放
    function startPlayback() {
        if (!selectedTrack || !port || isPlaying) return;

        isPlaying = true;
        startTime = performance.now();
        currentEventIndex = 0;
        scheduledEvents = [];

        playBtn.disabled = true;
        stopBtn.disabled = false;
        statusText.textContent = '播放中...';
        logSerialMessage('开始播放轨道');

        scheduleEvents();
    }

    // 停止播放
    async function stopPlayback() {
        if (!isPlaying) return;

        isPlaying = false;
        clearScheduledEvents();

        if (currentWriter) {
            currentWriter.releaseLock();
            currentWriter = null;
        }

        playBtn.disabled = false;
        stopBtn.disabled = true;
        statusText.textContent = '播放已停止';
        logSerialMessage('播放已停止');

        // 发送停止命令到串口
        if (port && port.writable) {
            try {
                // 创建6字节的停止命令 (全0x00)
                const stopCommand = new Uint8Array([0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]);



                // 检查流是否已锁定
                if (port.writable.locked) {
                    console.warn('输出流已被锁定，无法发送停止命令');
                    return;
                }

                // 获取新writer并发送停止命令
                currentWriter = port.writable.getWriter();
                await currentWriter.write(stopCommand);
                console.log('已发送停止命令:', stopCommand);
                logSerialMessage(`发送停止命令: ${Array.from(stopCommand).map(b => b.toString(16).padStart(2, '0')).join(' ')}`);

                // 获取reader用于读取响应
                if (port.readable && !port.readable.locked) {
                    currentReader = port.readable.getReader();
                    try {
                        const { value, done } = await currentReader.read();
                        if (!done && value) {
                            const textDecoder = new TextDecoder();
                            const response = textDecoder.decode(value);
                            console.log('设备响应:', response);
                            logSerialMessage(`设备响应: ${response.trim()}`);
                        }
                    } catch (e) {
                        console.warn('读取设备响应失败:', e);
                    }
                }
            } catch (error) {
                console.error('发送停止命令失败:', error);
                logSerialMessage(`发送停止命令错误: ${error.message}`);

            }
        }
    }

    // 调度事件
    let lastEventTime = 0;
    let microsecondsPerBeat = 500000; // 默认120bpm
    let ticksPerBeat = 480; // 默认ticks/beat
    let timeSignature = { numerator: 4, denominator: 4 }; // 默认4/4拍

    function scheduleEvents() {
        if (!isPlaying || !selectedTrack) return;

        const now = performance.now();
        if (!startTime) {
            startTime = now;
            lastEventTime = 0;

            // 从MIDI文件头获取时间分割信息
            if (midiData) {
                if (midiData.timeDivision & 0x8000) {
                    // SMPTE格式 - 暂不支持
                    console.error('SMPTE时间格式不支持');
                    ticksPerBeat = 480;
                } else {
                    // 基于ticks/beat的格式
                    ticksPerBeat = midiData.timeDivision;
                }

                // 查找初始速度设置
                for (const track of midiData.tracks) {
                    for (const event of track) {
                        if (event.type === 'meta' && event.metaType === 0x51) {
                            microsecondsPerBeat = event.tempo;
                            break;
                        }
                    }
                }
            }

            console.log('初始化调度参数:', {
                startTime,
                ticksPerBeat,
                initialTempo: Math.round(60000000 / microsecondsPerBeat),
                timeDivision: midiData ? midiData.timeDivision : '默认'
            });
        }

        const elapsedTime = (now - startTime) / 1000; // 转换为秒

        // 查找并发送到期事件
        while (currentEventIndex < selectedTrack.events.length) {
            const event = selectedTrack.events[currentEventIndex];

            // 处理元事件
            if (event.type === 'meta') {
                if (event.metaType === 0x51) { // 速度变化
                    microsecondsPerBeat = event.tempo;
                    console.log('速度变化:', {
                        newTempo: Math.round(60000000 / microsecondsPerBeat),
                        microsecondsPerBeat
                    });
                } else if (event.metaType === 0x58) { // 拍号变化
                    timeSignature = {
                        numerator: event.timeSignature.numerator,
                        denominator: event.timeSignature.denominator
                    };
                    console.log('拍号变化:', timeSignature);
                }
                currentEventIndex++;
                continue;
            }

            // 计算事件时间(秒)
            const beats = event.deltaTime / ticksPerBeat;
            const seconds = beats * (microsecondsPerBeat / 1000000);
            const eventTime = lastEventTime + seconds;

            console.log('事件调度:', {
                deltaTime: event.deltaTime,
                beats: beats.toFixed(4),
                seconds: seconds.toFixed(6),
                eventTime: eventTime.toFixed(6),
                elapsedTime: elapsedTime.toFixed(6),
                tempo: Math.round(60000000 / microsecondsPerBeat),
                ticksPerBeat
            });

            // 如果事件时间小于当前经过时间，发送事件
            if (eventTime <= elapsedTime) {
                sendMidiEvent(event);
                lastEventTime = eventTime;
                currentEventIndex++;
            } else {
                // 事件在将来，停止检查
                break;
            }
        }

        // 计算下一帧时间(动态调整)
        const nextCheckIn = Math.max(1, (lastEventTime - elapsedTime) * 1000 / 2);

        // 继续调度
        scheduledEvents.push(setTimeout(scheduleEvents, nextCheckIn));

        // 检查是否播放完成
        if (currentEventIndex >= selectedTrack.events.length) {
            stopPlayback();
            statusText.textContent = '播放完成';
            logSerialMessage('轨道播放完成');
        }
    }

    // 计算事件时间
    function calculateEventTime(event) {
        if (!event) return 0;

        // 计算事件时间(秒)
        const beats = event.deltaTime / ticksPerBeat;
        const seconds = beats * (microsecondsPerBeat / 1000000);
        return seconds;
    }

    // 发送MIDI事件到串口
    let currentWriter = null;
    let currentReader = null;
    let lastSendTime = 0;
    const MIN_SEND_INTERVAL = 5; // 最小发送间隔(毫秒) - 从5增加到30ms

    async function sendMidiEvent(event) {
        if (isPlaying === false || !event || !selectedTrack) return;
        if (!port || !port.writable) {
            console.warn('串口不可用，无法发送事件');
            return;
        }

        const plannedTime = lastEventTime + (event.deltaTime / ticksPerBeat) * (microsecondsPerBeat / 1000000);
        const actualTime = performance.now() / 1000 - startTime / 1000;
        const timeDiff = actualTime - plannedTime;

        // 检查最小发送间隔
        const now = performance.now();
        if (now - lastSendTime < MIN_SEND_INTERVAL) {
            console.log(`跳过发送，距离上次发送仅${now - lastSendTime}ms`);
            return;
        }
        lastSendTime = now;

        try {
            // 检查并释放之前的writer
            if (currentWriter) {
                try {
                    await currentWriter.ready;
                    currentWriter.releaseLock();
                } catch (e) {
                    console.warn('释放writer时出错:', e);
                }
                currentWriter = null;
            }

            // 检查流是否已锁定
            if (port.writable.locked) {
                console.warn('输出流已被锁定，无法发送事件');
                return;
            }

            // 获取新writer并发送事件
            currentWriter = port.writable.getWriter();
            const message = formatMidiMessage(event);

            if (message) {
                const sendStart = performance.now();
                await currentWriter.write(message); // 直接发送二进制数据
                const sendDuration = performance.now() - sendStart;

                console.log('MIDI事件发送详情:', {
                    eventType: event.type,
                    note: event.noteNumber,
                    velocity: event.velocity,
                    plannedTime: plannedTime.toFixed(6),
                    actualTime: actualTime.toFixed(6),
                    timeDiff: timeDiff.toFixed(6),
                    sendDuration: sendDuration.toFixed(3)
                });

                logSerialMessage(`发送: ${Array.from(message).map(b => b.toString(16).padStart(2, '0')).join(' ')} (延迟: ${(timeDiff * 1000).toFixed(2)}ms)`);
            }
        } catch (error) {
            logSerialMessage(`发送错误: ${error.message}`);
            console.error('发送MIDI事件错误:', error, {
                event,
                plannedTime,
                actualTime,
                timeDiff
            });
            stopPlayback();
        } finally {
            // 释放writer
            if (currentWriter && !port.writable.locked) {
                try {
                    await currentWriter.ready;
                    currentWriter.releaseLock();
                    currentWriter = null;
                } catch (e) {
                    console.warn('释放writer时出错:', e);
                }
            }
        }
    }

    // 格式化MIDI消息为STM32设备要求的6字节格式
    function formatMidiMessage(event) {
        console.log('格式化MIDI事件:', event);

        // 只处理Note On和Note Off事件
        const isNoteOn = event.type === 'noteOn';
        const isNoteOff = event.type === 'noteOff' || (isNoteOn && event.velocity === 0);

        if (!isNoteOn && !isNoteOff) {
            console.log('忽略非音符事件:', event.type);
            return null; // 忽略其他类型事件
        }

        // 检查必要属性
        if (typeof event.noteNumber === 'undefined' || typeof event.velocity === 'undefined') {
            console.error('音符事件缺少必要属性:', {
                noteNumber: event.noteNumber,
                velocity: event.velocity
            });
            return null;
        }

        // 创建6字节的Uint8Array缓冲区
        const buffer = new Uint8Array(6);

        // 时间戳(大端序4字节) - 使用绝对时间
        const time = Math.round(event.absoluteTime * 1000); // 转换为毫秒
        buffer[0] = (time >> 24) & 0xFF;
        buffer[1] = (time >> 16) & 0xFF;
        buffer[2] = (time >> 8) & 0xFF;
        buffer[3] = time & 0xFF;

        // 音符(1字节) - 使用noteNumber属性
        buffer[4] = event.noteNumber;
        console.log('音符值:', event.noteNumber);

        // 力度/类型(1字节): bit7-1=力度, bit0=类型(1=Note On, 0=Note Off)
        const velocity = isNoteOn ? Math.min(127, event.velocity) : 0;
        const type = isNoteOn ? 1 : 0;
        buffer[5] = (velocity << 1) | type;
        console.log('力度值:', velocity, '类型:', type);

        console.log('生成的MIDI消息:', Array.from(buffer).map(b => b.toString(16).padStart(2, '0')).join(' '));
        return buffer;
    }

    // 清除已调度的事件
    function clearScheduledEvents() {
        scheduledEvents.forEach(timerId => clearTimeout(timerId));
        scheduledEvents = [];
    }

    // 记录串口日志
    function logSerialMessage(message) {
        const timestamp = new Date().toLocaleTimeString();
        serialLog.textContent += `[${timestamp}] ${message}\n`;
        serialLog.scrollTop = serialLog.scrollHeight;
    }

    // 初始化UI状态
    function initUI() {
        trackSelect.disabled = true;
        playBtn.disabled = true;
        stopBtn.disabled = true;
    }

    initUI();
});